package com.yequan.leetcode.linkedlist.hascycle_141;

import com.yequan.leetcode.linkedlist.ListNode;

import java.util.HashSet;
import java.util.Set;

/**
 * //给定一个链表，判断链表中是否有环。
 * //
 * // 为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。
 * //
 * // 示例 1：
 * //
 * // 输入：head = [3,2,0,-4], pos = 1
 * //输出：true
 * //解释：链表中有一个环，其尾部连接到第二个节点。
 * //
 * // 示例 2：
 * //
 * // 输入：head = [1,2], pos = 0
 * //输出：true
 * //解释：链表中有一个环，其尾部连接到第一个节点。
 * <p>
 * // 示例 3：
 * //
 * // 输入：head = [1], pos = -1
 * //输出：false
 * //解释：链表中没有环。
 * //
 * //
 * // 进阶：
 * //
 * // 你能用 O(1)（即，常量）内存解决此问题吗？
 * // Related Topics 链表 双指针
 *
 * @author : Administrator
 * @date : 2020/3/17
 */
public class HasCycle {


    /**
     * 遍历法: 将访问过的节点存入 Set 中,如果有则表示有环
     *
     * @param head
     * @return
     */
    public boolean hasCycle1(ListNode head) {
        if (null == head || head.next == null) {
            return false;
        }
        Set<ListNode> nodeSet = new HashSet<>();
        while (head != null) {
            if (!nodeSet.add(head)) {
                return true;
            }
            head = head.next;
        }
        return false;
    }

    /**
     * 快慢指针法:
     * 快指针一次往前移动 2 步,慢指针往前移动 1 步,如果没有环则快指针一定大于慢指针,否则迟早相遇
     *
     * @param head
     * @return
     */
    public boolean hasCycle2(ListNode head) {
        if (null == head || head.next == null) {
            return false;
        }
        ListNode slowIndex = head;
        ListNode fastIndex = head.next;
        while (slowIndex != fastIndex) {
            //快指针走得快,只需判断快指针是否为空
            if (fastIndex == null || fastIndex.next == null) {
                return false;
            }
            slowIndex = slowIndex.next;
            fastIndex = fastIndex.next.next;
        }
        return true;
    }

    public boolean hasCycle3(ListNode head) {
        if (null == head || head.next == null){
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while (slow != fast){
            if (fast == null || fast.next==null){
                return false;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        return true;
    }

}
